﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace AMEE.PlaneDetection
{
    /// <summary>
    /// 3D Plane structure with normal vector and distance from origin.<para>
    /// Plane definition: <c>a * x + b * y + c * z + d = 0</c>a.
    /// </para>
    /// </summary>
    public struct Plane
    {
        /// <summary>
        /// Gets or sets the constant <c>a</c> in the plane
        /// definition <c>a * x + b * y + c * z + d = 0</c>.
        /// </summary>
        public float A;

        /// <summary>
        /// Gets or sets the constant <c>b</c> in the plane
        /// definition <c>a * x + b * y + c * z + d = 0</c>.
        /// </summary>
        public float B;

        /// <summary>
        /// Gets or sets the constant <c>c</c> in the plane
        /// definition <c>a * x + b * y + c * z + d = 0</c>.
        /// </summary>
        public float C;

        /// <summary>
        /// Gets or sets the distance offset between the plane and the origin<para>
        /// (the constant <c>d</c> in the plane
        /// definition <c>a * x + b * y + c * z + d = 0)</c>.</para>
        /// </summary>
        public float Offset;

        /// <summary>
        /// Gets the normal vector (x,y,z)<sup>T</sup> = (A,B,C)<sup>T</sup>
        /// </summary>
        /// <value>
        /// The normal.
        /// </value>
        public Tuple<float, float, float> Normal {
            get {
                return new Tuple<float, float, float>(A, B, C);
            }
        }

        public override string ToString() {
            return string.Format("{0:N3}·x + {1:N3}·y + {2:N3}·z + {3:N4} = 0");
        }

        public override bool Equals(object obj) {
            if (!(obj is Plane)) {
                return false;
            }
            Plane other = (Plane)obj;
            if (!other.Normal.Equals(this.Normal)) {
                return false;
            }
            if (other.Offset != this.Offset) {
                return false;
            }
            return true;
        }

        public override int GetHashCode() {
            int hash = 17;
            hash = 31 * hash + this.Normal.GetHashCode();
            hash = hash * 13 + this.Offset.GetHashCode();
            return hash;
        }
        
    }
}
